added *_HUMAN_READABLE styles to xcsv
authorparkrrrr <parkrrrr@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Wed, 21 Jul 2004 20:13:00 +0000 (20:13 +0000)
committerparkrrrr <parkrrrr@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Wed, 21 Jul 2004 20:13:00 +0000 (20:13 +0000)
gpsbabel/csv_util.c
gpsbabel/style/README.style

index 5ab7e24ad4ccccc8b4d59f6d6bb0180bb106bc74..6d26386335524936e0e9c53eca1505b3368f1975 100644 (file)
@@ -312,6 +312,172 @@ decdir_to_dec(const char * decdir)
     return(rval * sign);
 }
 
+
+/*****************************************************************************
+ * human_to_dec() - convert a "human-readable" lat and/or lon to decimal
+ * usage: human_to_dec( "N 41° 09.12' W 085° 09.36'", &lat, &lon );
+ *        human_to_dec( "41 9 5.652 N", &lat, &lon );
+ *****************************************************************************/
+
+static void
+human_to_dec( const char *instr, double *outlat, double *outlon )
+{
+    double unk[3] = {999,999,999};
+    double lat[3] = {999,999,999};
+    double lon[3] = {999,999,999};
+    int    latsign = 0;
+    int    lonsign = 0;
+   
+    const char *cur;
+    double *numres = unk;
+    int numind = 0;
+    
+    cur = instr;
+       
+    while ( cur && *cur ) {
+       switch (*cur) {
+           case 'n': case 's': case 'N': case 'S':
+               if ( numind && numind < 3 ) {
+                       numind = 0;
+               }
+               lat[0] = unk[0];
+               lat[1] = unk[1];
+               lat[2] = unk[2];
+               
+               numres = lat;
+               
+               if ( *cur == 'n' || *cur == 'N' ) 
+                   latsign = 1;
+               else
+                   latsign = -1;
+               cur++;
+               break;
+           case 'w': case 'e': case 'W': case 'E':
+               if ( numind && numind < 3 ) {
+                       numind = 0;
+               }
+               lon[0] = unk[0];
+               lon[1] = unk[1];
+               lon[2] = unk[2];
+               
+               numres = lon;
+               
+               if ( *cur == 'e' || *cur == 'E' ) 
+                   lonsign = 1;
+               else
+                   lonsign = -1;
+               cur++;
+               break;
+           case '1': case '2': case '3': case '4': case '5':
+           case '6': case '7': case '8': case '9': case '0': case '.':
+               numres[numind] = atof(cur);
+               while (cur && *cur && strchr("1234567890.",*cur)) cur++;
+               break;
+           default:
+               if (numres[numind] != 999) {
+                   numind++;
+                   if ( numind > 2 ) {
+                       numres = unk;
+                       numind = 0;
+                   }
+               }
+               cur++;
+               break;      
+       }
+    }
+    
+    if ( outlat ) {
+       if ( lat[0] != 999 ) *outlat = lat[0];
+       if ( lat[1] != 999 ) *outlat += lat[1]/60.0;
+       if ( lat[2] != 999 ) *outlat += lat[2]/3600.0;
+       if ( latsign ) *outlat *= latsign;
+    }
+    if ( outlon ) {
+       if ( lon[0] != 999 ) *outlon = lon[0];
+       if ( lon[1] != 999 ) *outlon += lon[1]/60.0;
+       if ( lon[2] != 999 ) *outlon += lon[2]/3600.0;
+       if ( lonsign ) *outlon *= lonsign;
+    }
+}
+
+/*
+ * dec_to_human - convert decimal degrees to human readable
+ */
+
+void
+dec_to_human( char *buff, const char *format, const char *dirs, double val )
+{
+    char *subformat = NULL;
+    const char *formatptr = NULL;
+    char *percent = NULL;
+    char *type = NULL;
+    
+    int  index = 0; 
+    int  intvals[3] = {0,0,0};
+    double  dblvals[3] = {0,0,0};
+    int  sign = 0;
+    
+    sign = (val < 0) ? 0 : 1;
+    
+    dblvals[0] = fabs(val);
+    intvals[0] = (int)dblvals[0];
+    dblvals[1] = 60*(dblvals[0]-intvals[0]);
+    intvals[1] = (int)dblvals[1];
+    dblvals[2] = 60*(dblvals[1]-intvals[1]);
+    intvals[2] = (int)dblvals[2];
+    
+    subformat = xmalloc( strlen(format)+2);
+    formatptr = format;
+    
+    buff[0] = '\0';
+    
+    while ( formatptr && *formatptr ) {
+       strcpy( subformat, formatptr );
+       percent = strchr( subformat, '%' );
+       if ( percent ) {
+           type = percent+1+strcspn( percent+1, "cdiouxXeEfgG%" );
+           *(type+1) = '\0';
+           switch( *type ) {
+               case 'c':
+                   sprintf( buff+strlen(buff), subformat, dirs[sign] );
+                   break;
+               case 'd':
+               case 'i':
+               case 'o':
+               case 'u':
+               case 'x':
+               case 'X':
+                   if (index>2) fatal(MYNAME ": too many format specifiers\n");
+                   sprintf( buff+strlen(buff), subformat, intvals[index]);
+                   index++;
+                   break;
+               case 'e':
+               case 'E':
+               case 'f':
+               case 'g':
+               case 'G':
+                   if (index>2) fatal(MYNAME ": too many format specifiers\n");
+                   sprintf( buff+strlen(buff), subformat, dblvals[index]);
+                   index++;
+                   break;
+               case '%':
+                   sprintf( buff+strlen(buff), subformat );
+                   break;
+               default:
+                   fatal(MYNAME ": invalid format specifier\n");
+                   break;
+
+           }
+       }
+       else {
+           sprintf( buff+strlen(buff), subformat );
+       }
+       formatptr += strlen(subformat);
+    } // end while;
+    
+    xfree(subformat);
+}      
+
 /*****************************************************************************/
 /* xcsv_file_init() - prepare xcsv_file for first use.                       */
 /*****************************************************************************/
@@ -452,6 +618,9 @@ xcsv_parse_val(const char *s, waypoint *wpt, const field_map_t *fmp)
        /* latitude as a 32 bit integer offset */
        wpt->latitude = intdeg_to_dec(atof(s), 1);
     } else
+    if ( strcmp(fmp->key, "LAT_HUMAN_READABLE") == 0) {
+       human_to_dec( s, &wpt->latitude, &wpt->longitude );
+    } else
     /* LONGITUDE CONVERSIONS ***********************************************/
     if (strcmp(fmp->key, "LON_DECIMAL") == 0) {
        /* longitude as a pure decimal value */
@@ -466,7 +635,13 @@ xcsv_parse_val(const char *s, waypoint *wpt, const field_map_t *fmp)
        /* longitude as a 32 bit integer offset  */
        wpt->longitude = intdeg_to_dec(atof(s), 0);
     } else
-
+    if ( strcmp(fmp->key, "LON_HUMAN_READABLE") == 0) {
+       human_to_dec( s, &wpt->latitude, &wpt->longitude );
+    } else
+    /* LAT AND LON CONVERSIONS ********************************************/
+    if ( strcmp(fmp->key, "LATLON_HUMAN_READABLE") == 0) {
+       human_to_dec( s, &wpt->latitude, &wpt->longitude );
+    } else
     /* DIRECTIONS **********************************************************/
     if (strcmp(fmp->key, "LAT_DIR") == 0) {
        /* latitude N/S.  Ignore on input for now */
@@ -736,6 +911,9 @@ xcsv_waypt_pr(const waypoint *wpt)
             sprintf(buff, fmp->printfc,
               dec_to_intdeg(wpt->latitude, 1));
         } else
+       if (strcmp(fmp->key, "LAT_HUMAN_READABLE") == 0) {
+           dec_to_human( buff, fmp->printfc, "SN", wpt->latitude );
+       } else
 
         /* LONGITUDE CONVERSIONS*********************************************/
         if (strcmp(fmp->key, "LON_DECIMAL") == 0) {
@@ -759,6 +937,15 @@ xcsv_waypt_pr(const waypoint *wpt)
             sprintf(buff, fmp->printfc,
               dec_to_intdeg(wpt->longitude, 0));
         } else
+       if (strcmp(fmp->key, "LON_HUMAN_READABLE") == 0) {
+           dec_to_human( buff, fmp->printfc, "WE", wpt->longitude );
+       } else
+       if (strcmp(fmp->key, "LATLON_HUMAN_READABLE") == 0) {
+           dec_to_human( buff, fmp->printfc, "SN", wpt->latitude );
+           if ( !isspace(buff[strlen(buff)])) strcat( buff, " " );
+           dec_to_human( buff+strlen(buff), fmp->printfc, "WE", 
+                           wpt->longitude );
+       } else
 
         /* DIRECTIONS *******************************************************/
         if (strcmp(fmp->key, "LAT_DIR") == 0) {
index 5deb5799c0e2eb26e77877c632f1462233b510ae..78971a04c2f98beabcfefdfc020b817ea2bb74cd 100644 (file)
@@ -275,6 +275,34 @@ The fields used by the XCSV parser are as follows:
    hemisphere of the latitude.  LON_DIR returns 'E' or 'W' depending on
    the hemisphere of the longitude.
 
+ o LAT_HUMAN_READABLE
+   LAT_HUMAN_READABLE defines LATITUDE in a human-readable format.  This 
+   format is probably the most expressive format.  It is similar to 
+   LAT_DECIMALDIR in that it requires multiple printf conversions, but it
+   is far more flexible as to the contents of those conversions.  On read,
+   the printf conversions are ignored and GPSBabel attempts to determine the
+   latitude and longitude based on what is in the file.
+
+   example: IFIELD LAT_HUMAN_READABLE,"","%c %d %f"   (writes N 31 40.000)
+   example: IFIELD LAT_HUMAN_READABLE,"","%d deg %f min %c"
+                                         (writes "31 deg 40.000 min N")
+            Note that this string will confuse the reading routine due 
+            to the letter "n" in "min" and the letter "e" in "deg."
+   example: IFIELD LAT_HUMAN_READABLE,"","%d %d %f%c" (writes 31 40 00.000N)
+
+ o LON_HUMAN_READABLE
+   See LAT_HUMAN_READABLE except LON_HUMAN_READABLE defines LONGITUDE.
+
+ o LATLON_HUMAN_READABLE
+   LATLON_HUMAN_READABLE is like LAT_HUMAN_READABLE and LON_HUMAN_READABLE
+   except that it reads and writes both latitude and longitude as a single 
+   field.  On write, the same format specifier is used for both coordinates.
+   On read, GPSBabel does exactly the same thing it does for 
+   LAT_HUMAN_READABLE or LON_HUMAN_READABLE.
+
+   example: IFIELD LATLON_HUMAN_READABLE,"","%c %d %f"
+            (writes "N 31 40.126 W 85 09.62" as a single field)
+
  o ALT_FEET
    ALT_FEET is the position's ALTITUDE in FEET.  This value is treated as 
    a SIGNED DOUBLE PRECISION FLOAT and requires a FLOATING POINT printf